package com.dtwave.wechat.service.provider.core.wx;

import com.dtwave.wechat.service.provider.common.enums.EnumMethod;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import com.dtwave.wechat.service.provider.common.utils.URLEncodeUtil;
import com.dtwave.wechat.service.provider.common.utils.WxHttpRequestUtil;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @Auther: liuwenxiang
 * @Date: 2019/2/23 15:38
 * @Description:
 */
public class WeiXinMethodUtil {

    private static Logger logger = LoggerFactory.getLogger(WeiXinMethodUtil.class);

    /**
     * 获取access_token
     *
     * @param appid
     *            凭证
     * @param appsecret
     *            密钥
     * @return
     */
    public static AccessToken getAccessToken(String appid, String appsecret, int type) {
        AccessToken accessToken = null;
        String requestUrl = WeiXinApi.access_token_url.replace("APPID", appid).replace("APPSECRET", appsecret);
        if (type == 1) {
            requestUrl = WeiXinApi.company_access_token_url.replace("CORPID", appid).replace("CORPSECRET", appsecret);
            System.err.println(requestUrl);
        }
        JSONObject jsonObject = WxHttpRequestUtil.httpRequest(requestUrl, EnumMethod.GET.name(), null);
        if (jsonObject == null) {
            jsonObject = WxHttpRequestUtil.httpRequest(requestUrl, EnumMethod.GET.name(), null);
        }
        // 如果请求成功
        if (null != jsonObject) {
            try {
                accessToken = new AccessToken();
                accessToken.setToken(jsonObject.getString("access_token"));
                accessToken.setExpiresIn(jsonObject.getInt("expires_in"));
            } catch (JSONException e) {
                accessToken = null;
                // 获取token失败
            }
        }
        System.out.println("******===="+accessToken.getToken());
        return accessToken;
    }



    /**
     * 方法名：getWxConfig</br>
     * 详述：获取微信的配置信息 </br>
     * 开发人员：souvc </br>
     * 创建时间：2016-1-5 </br>
     *
     * @param request
     * @return 说明返回值含义
     * @throws 说明发生此异常的条件
     */
    public static Map<String, Object> getWxConfig(String url, HttpServletRequest request, AccessToken accessToken, String appId) {
        Map<String, Object> ret = new HashMap<String, Object>();

        /**
         * 获取signature主要分四部
         * 1、使用APPID和APPSecret获取access_token；
         *
         * 2、使用access_token获取jsapi_ticket ；
         *
         * 3、用时间戳、随机数、jsapi_ticket和要访问的url按照签名算法拼接字符串；
         *
         * 4、对第三步的字符串进行SHA1加密，得到签名。
         *
         * 注意事项：
         *
         * 1、签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。
         **** 2、签名用的url必须是调用JS接口页面的完整URL。
         * 3、出于安全考虑，开发者必须在服务器端实现签名的逻辑。
         */
        //String requestUrl = request.getRequestURL().toString();
        String requestUrl =  url;
        String access_token = "";
        String jsapi_ticket = "";
        String timestamp = Long.toString(System.currentTimeMillis() / 1000); // 必填，生成签名的时间戳
        String nonceStr = UUID.randomUUID().toString(); // 必填，生成签名的随机串
        if (accessToken != null) {
            // 要注意，access_token需要缓存
            access_token = accessToken.getToken();

            WXjsTicket wXjsTicket = getWXjsTicket(access_token);
            if (access_token != null) {
                jsapi_ticket = wXjsTicket.getJsTicket();
            }
        }
        String signature = "";
        // 注意这里参数名必须全部小写，且必须有序
        String sign = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonceStr + "&timestamp=" + timestamp + "&url="
                +url;
        System.out.println(sign);
        try {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(sign.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        ret.put("appId", appId);
        ret.put("timestamp", timestamp);
        ret.put("nonceStr", nonceStr);
        ret.put("signature", signature);
        return ret;
    }



    public static WXjsTicket getWXjsTicket(String accessToken) {
        /**
         * 通过tonken获取jsTicket，为获取签名提供参数
         */
        WXjsTicket wXjsTicket = null;
        String requestUrl = WeiXinApi.get_jsapi.replace("ACCESS_TOKEN", accessToken);
        // 发起GET请求获取凭证
        JSONObject jsonObject = WxHttpRequestUtil.httpRequest(requestUrl, "GET", null);
        if (null != jsonObject) {
            try {
                wXjsTicket = new WXjsTicket();
                wXjsTicket.setJsTicket(jsonObject.getString("ticket"));
                wXjsTicket.setJsTicketExpiresIn(jsonObject.getInt("expires_in"));
            } catch (JSONException e) {
                wXjsTicket = null;
                // 获取wXjsTicket失败
                logger.error("获取wXjsTicket失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"),
                        jsonObject.getString("errmsg"));
            }
        }else{
            logger.error("获取wXjsTicket失败， jsonObject为空，errcode:{} errmsg:{}", jsonObject.getInt("errcode"),
                    jsonObject.getString("errmsg"));
        }

        return wXjsTicket;
    }



    /**
     * 方法名：byteToHex</br>
     * 详述：字符串加密辅助方法 </br>
     * 开发人员：souvc </br>
     * 创建时间：2016-1-5 </br>
     *
     * @param hash
     * @return 说明返回值含义
     * @throws 说明发生此异常的条件
     */
    private static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash) {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;

    }


    public static String getDepartmentList(String token){
        //拼接请求地址
        String requestUrl=WeiXinApi.get_department_list.replace("ACCESS_TOKEN",token);
        System.out.println("9999999999999999"+token);
        //创建成员
        JSONObject jsonObject=WxHttpRequestUtil.httpRequest(requestUrl, "GET", null);
        if(null!=jsonObject){
            System.out.println(jsonObject.toString()+"=====");
            if (jsonObject.containsKey("errcode") ){ //是否有错误
                if (jsonObject.getString("errcode").equals("40029")){  //是否为code错误
                    String url = "https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token="+token;
                    jsonObject=WxHttpRequestUtil.httpRequest(url, "POST", null);
                    System.out.println("-----------"+jsonObject.toString());
                }
            }
        }else{
            System.out.println("获取授权失败");
        }
        return jsonObject.toString();
    }



    //获取通讯录列表
    public static String getSimpleList(String  department_id,String fetch_child,int status,AccessToken token){
        //拼接请求地址
        String requestUrl=WeiXinApi.get_simple_list.replace("ACCESS_TOKEN",token.getToken()).replace("DEPARTMENT_ID",department_id).replace("FETCH_CHILD",  department_id);
        System.out.println("9999999999999999"+token);
        //创建成员
        JSONObject jsonObject=WxHttpRequestUtil.httpRequest(requestUrl, "POST", null);
        if(null!=jsonObject){
            System.out.println(jsonObject.toString()+"=====");
            if (jsonObject.containsKey("errcode") ){ //是否有错误
                if (jsonObject.getString("errcode").equals("40029")){  //是否为code错误
                    String url = "https://qyapi.weixin.qq.com/cgi-bin/user/simplelist?access_token="
                            +token.getToken()+"&department_id="+department_id+"&fetch_child="+fetch_child;
                    jsonObject=WxHttpRequestUtil.httpRequest(url, "POST", null);
                    System.out.println("-----------"+jsonObject.toString());
                }
            }
        }else{
            System.out.println("获取授权失败");
        }
        return jsonObject.toString();
    }



    /**
     * 获取点击菜单上携带的code
     * @param appid 企业的CorpID
     * @param redirect_uri 授权后重定向的回调链接地址，请使用urlencode对链接进行处理
     * @param response_type 返回类型，此时固定为：code
     * @param scope 应用授权作用域，此时固定为：snsapi_base
     * @param state 重定向后会带上state参数，企业可以填写a-zA-Z0-9的参数值
     * @param #wechat_redirect 微信终端使用此参数判断是否需要带上身份信息
     * 员工点击后，页面将跳转至 redirect_uri/?code=CODE&state=STATE，企业可根据code参数获得员工的userid
     * */
    public static String GetCode(String cropId,String backUrl){
        String get_code_url = "";
        try {
            get_code_url = WeiXinApi.get_code.replace("CORPID", cropId).replace("REDIRECT_URI", URLEncodeUtil.urlDecodeUTF8(backUrl) );
        } catch (Exception e) {
            e.printStackTrace();
        }
        return get_code_url;
    }




    /**
     * 根据code获取成员信息
     * @param access_token 调用接口凭证
     * @param code 通过员工授权获取到的code，每次员工授权带上的code将不一样，code只能使用一次，5分钟未被使用自动过期
     * @param agentid 跳转链接时所在的企业应用ID
     * *******获取userId的逻辑：
     * 管理员须拥有agent的使用权限；agentid必须和跳转链接时所在的企业应用ID相同
     * 微信会在点击的自定义菜单上加上一个与userId相关联的code在菜单的url上，点击url访问后台，后台再根据code去访问微信接口获取userId
     *     通过code获取userId，每个code只能使用一次，所以前台要缓存userId,避免页面刷新时，
     *
     * */
    public static String GetUserID (String access_token,String code ,String agentid){
        String UserId = "";
        String CODE_TO_USERINFO = WeiXinApi.code_to_userinfo.replace("ACCESS_TOKEN", access_token).replace("CODE", code).replace("AGENTID", agentid);
        System.out.println("11111111111111111111");
        logger.info("11111111111111111111");
        JSONObject jsonobject = WxHttpRequestUtil.httpRequest(CODE_TO_USERINFO, "GET", null);
        System.out.println("22222222222222222222");
        logger.info("22222222222222222222");
        if(null!=jsonobject){
            System.out.println("3333333333333333333333");
            logger.info("3333333333333333333333");
            if (jsonobject.containsKey("errcode") ){ //是否有错误
                System.out.println("44444444444444444444");
                if (jsonobject.getString("errcode").equals("40029")){  //是否为code错误
                    System.out.println("5555555555555555555");
                    String newstr=   CODE_TO_USERINFO.substring(0, CODE_TO_USERINFO.indexOf("&code=")).concat("&code=").concat(code); //去除错误的code加入正确的
                    System.out.println("newstr:"+newstr);
                    jsonobject=WxHttpRequestUtil.httpRequest(newstr, "GET", null);
                    System.out.println("-----------"+jsonobject.toString());
                }
            }
            logger.info(jsonobject+"6666666666666666666666666"+jsonobject.getString("UserId"));
            System.out.println("6666666666666666666666666");
            UserId = jsonobject.getString("UserId");
            if(!"".equals(UserId)){
                System.out.println("获取信息成功，o(∩_∩)o ————UserID:"+UserId);
            }else{
                int errorrcode = jsonobject.getInt("errcode");
                String errmsg = jsonobject.getString("errmsg");
                logger.info("错误码："+errorrcode+"————"+"错误信息："+errmsg);
                System.out.println("错误码："+errorrcode+"————"+"错误信息："+errmsg);
            }
        }else{
            logger.info("获取授权失败了，●﹏●，自己找原因。。。");
            System.out.println("获取授权失败了，●﹏●，自己找原因。。。");
        }
        return UserId;
    }


    public static int Send_msg(WechatRequest wechatRequest,String msgtype,String access_token) {
        int errCode = 0;
        StringBuffer sb = new StringBuffer();
        // 发送消息url地址
        sb.append("{");
        sb.append("\"touser\":" + "\"" + wechatRequest.getTouser() + "\",");
        sb.append("\"toparty\":" + "\"" + wechatRequest.getToparty() + "\",");
        sb.append("\"totag\":" + "\"" + wechatRequest.getTotag() + "\",");
        sb.append("\"msgtype\":" + "\"" + wechatRequest.getMsgType() + "\",");
        sb.append("\"agentid\":" + "\"" + wechatRequest.getAgentid() + "\",");
        if (msgtype.equals("text")) {
            sb.append("\"text\":" + "{");
            sb.append("\"content\":" + "\"" + wechatRequest.getContent() + "\"");
            sb.append("},");
        } else if (msgtype.equals("image")) {
            sb.append("\"image\":" + "{");
            sb.append("\"media_id\":" + "\"" + wechatRequest.getMediaId() + "\"");
            sb.append("},");
        } else if (msgtype.equals("voice")) {
            sb.append("\"voice\":" + "{");
            sb.append("\"media_id\":" + "\"" + wechatRequest.getMediaId() + "\"");
            sb.append("},");
        } else if (msgtype.equals("video")) {
            sb.append("\"video\":" + "{");
            sb.append("\"media_id\":" + "\"" + wechatRequest.getMediaId() + "\",");
            sb.append("\"title\":" + "\"" + wechatRequest.getTitle() + "\",");
            sb.append("\"description\":" + "\"" + wechatRequest.getDescription() + "\"");
            sb.append("},");
        } else if (msgtype.equals("file")) {
            sb.append("\"file\":" + "{");
            sb.append("\"media_id\":" + "\"" + wechatRequest.getMediaId() + "\"");
            sb.append("},");
        } else if (msgtype.equals("news")) {
            sb.append("\"news\":" + "{");
            sb.append("\"articles\":" + "[");
            sb.append("{");
            sb.append("\"title\":" + "\"" + wechatRequest.getTitle() + "\",");
            sb.append("\"description\":" + "\"" + wechatRequest.getDescription() + "\",");
            sb.append("\"url\":" + "\"" + wechatRequest.getUrl() + "\",");
            sb.append("\"picurl\":" + "\"" + wechatRequest.getPicurl() + "\"");
            sb.append("}");
            sb.append("]");
            sb.append("},");
        }
        sb.append("\"safe\":" + "\"" + wechatRequest.getSafe() + "\"");
        sb.append("}");

        String PostData = String.format(sb.toString());
        System.out.println("********************向用户推送消息"+sb.toString());
        try {
            String POST_URL = WeiXinApi.post_url.replace("ACCESS_TOKEN", access_token);
            JSONObject jsonobject = WxHttpRequestUtil.httpRequest(POST_URL,  "POST", PostData);
            System.out.println("***********************************************"+"向用户推送消息成功*************************");
        } catch (Exception e) {
            System.out.println("***********************************************"+"向用户推送消息发生异常*************************"+e.getMessage());
            e.printStackTrace();
        }

        System.out.println(errCode+"============"+PostData);
        return errCode;
    }









}
